local tweenlib = require 'util.tween'
local easing = tweenlib.easing
local copyTables = tweenlib.copyTables
local performEasingOnSubject = tweenlib.performEasingOnSubject

-- Tween methods
local Tween = {}
setmetatable(Tween, Tween)
ac.tween = Tween 

---@param easing string 动画效果
---@param duration number 时间
function Tween:__call(easing, duration, subject, target)
    return setmetatable({
        duration = duration or 1.0,
        easing = easing or "线性",
        subject = subject,
        target = target,
        clock = 0,
    }, Tween)
end 

Tween.__index = {

    set = function(self, clock)
        assert(type(clock) == 'number', "clock 不是一个有效数字")
        if self.initial then 
            self.clock = clock
            if self.clock <= 0 then
                self.clock = 0
                copyTables(self.subject, self.initial)
            elseif self.clock >= self.duration then -- the tween has expired
                self.clock = self.duration
                copyTables(self.subject, self.target)
            else
              performEasingOnSubject(self.subject, self.target, self.initial, self.clock, self.duration, self.easing)
            end
            if self.callback then 
                self.callback(self, self.subject)
            end 
        end 
        return self
    end,

    reset = function(self, clock)
        self:set(0)
        return self 
    end,

    update = function(self, clock)
        assert(type(clock) == 'number', "clock 不是一个有效数字")
        self:set(self.clock + clock)
        return self.subject
    end,

    begin = function(self, subject)
        if self.initial then return self end;
        assert(type(subject) == 'table', "subject 不是一个表")
        for k,v in pairs(subject) do
            assert(type(v) == 'number', "subject 参数不是一个有效数字")
        end
        self.subject = subject
        return self
    end,

    after = function(self, target)
        if self.initial then return self end;
        local subject = self.subject
        assert(type(target) == 'table', "target 不是一个表")
        assert(type(subject) == 'table', "subject 参数缺失")
        for k,v in pairs(subject) do
            assert(target[k], "target 内部参数缺失")
        end
        self.target = target
        self.initial = self.initial or copyTables({}, self.target, self.subject)
        return self
    end,

}

return Tween
